home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-05-22 | 38.7 KB | 1,366 lines | [TEXT/MPCC] |
- //
- // File: TestFunctions.c
- //
- // Contains: QuickDraw 3D support for QuickTime VR movies.
- //
- // Written by: Tim Monroe
- // parts modeled on BoxMoov code by Nick Thompson, Rick Evans, and Robert Dierkes
- // and on code in QD3D book (by yours truly!)
- //
- // Copyright: © 1996 by Apple Computer, Inc., all rights reserved.
- //
- // Change History (most recent first):
- //
- // <14> 01/24/97 rtm slight adjustment to camera-setting algorithm
- // <13> 01/23/97 rtm reworked camera-setting algorithm; now it works fine!
- // (replaced VR3DObjects_RotateCamera[XY] with VR3DObjects_SetCamera)
- // <12> 01/20/97 rtm various small tweaks; nothing major
- // <11> 01/17/97 rtm further work on tilting; still unable to fix it entirely
- // <10> 01/16/97 rtm added VR3DObjects_SetCameraAspectRatio
- // and VR3DObjects_UpdateDrawContext to handle window resizing
- // <9> 01/14/97 rtm added polyhedron object to VR3DObjects_CreateModel
- // added static texture support
- // <8> 01/13/97 rtm added some object types to VR3DObjects_CreateModel
- // <7> 01/10/97 rtm added VR3DObjects_MCActionFilterProc
- // (later merged into ApplicationMCActionFilterProc)
- // <6> 01/09/97 rtm fixed jittering on pan/tilt/zoom;
- // fixed VR3DObjects_RotateCameraX for correct tilting
- // <5> 01/03/97 rtm added animation (that is, rotation) support for 3D objects
- // <4> 12/23/96 rtm further work on 3D overlay; fixed some jitters
- // <3> 12/20/96 rtm added zooming support;
- // implemented 3D overlay instead of 3D test window
- // <2> 12/16/96 rtm added 3D test window, intercept procedure
- // added QuickTime movie texture mapping support
- // <1> 12/13/96 rtm first file
- //
- //
- // This file provides functions to display 3D objects at specific locations in a panorama.
- //
- // Our strategy: QuickDraw 3D is a "slave" to VR: whenever the VR environment changes,
- // we change the QuickDraw 3D camera accordingly and render a new image to our view.
- // All this occurs in the prescreen buffer imaging complete procedure.
- //
- //
- // TODO:
- // + stop a window's movie sound immediately when a suspend or deactivate event is received (?)
- // + add volume control button to affect QT movie sound track (already coded, but needs testing on new build)
- // + add support for VR object nodes (?)
-
-
- // header files
- #include "TestFunctions.h"
-
- #include "MacFramework.h"
- #include "QTVRUtilities.h"
-
-
- // system headers
- #include <Windows.h>
- #include <Resources.h>
- #include <TextUtils.h>
- #include <fp.h>
-
-
- // global variables
- extern Boolean gHasQuickDraw3D; // is QuickDraw 3D available?
-
-
- // constants
- const RGBColor kClearColor = {0x0000, 0xffff, 0x0000};
- const RGBColor kWhiteColor = {0xffff, 0xffff, 0xffff};
-
-
- //////////
- //
- // VR3DObjects_Init
- // Initialize for QuickDraw 3D.
- //
- //////////
-
- void VR3DObjects_Init (void)
- {
- TQ3Status myStatus;
-
- // make sure that QuickDraw 3D is available;
- if (VR3DObjects_IsQD3DAvailable()) {
- gHasQuickDraw3D = true;
- } else {
- gHasQuickDraw3D = false;
- ShowWarning("\pQuickDraw 3D is not available in the current environment: ", 0);
- }
-
- // now perform any initialization
- if (gHasQuickDraw3D) {
- myStatus = Q3Initialize();
- if (myStatus != kQ3Success) {
- ShowWarning("\pCould not initialize QuickDraw 3D: ", 0);
- }
- }
- }
-
-
- //////////
- //
- // VR3DObjects_Stop
- // Clean up for QuickDraw 3D.
- //
- //////////
-
- void VR3DObjects_Stop (void)
- {
- TQ3Status myStatus;
-
- // perform any QD3D-related shutdown operations
- if (gHasQuickDraw3D) {
- myStatus = Q3Exit();
- if (myStatus != kQ3Success) {
- // ShowWarning("\pCould not exit QuickDraw 3D: ", 0);
- }
- }
- }
-
-
- //////////
- //
- // VR3DObjects_IsQD3DAvailable
- // Is QuickDraw 3D available in the present operating environment?
- //
- //////////
-
- Boolean VR3DObjects_IsQD3DAvailable (void)
- {
- return((Boolean)Q3Initialize != kUnresolvedSymbolAddress);
- }
-
-
- //////////
- //
- // VR3DObjects_InitWindowData
- // Initialize the window-specific 3D data.
- //
- //////////
-
- ApplicationDataHdl VR3DObjects_InitWindowData (WindowObject theWindowObject)
- {
- ApplicationDataHdl myAppData;
- TQ3Point3D myOrigin = {0.0, 0.0, -k3DObjectDistance};
- OSErr myErr;
- Rect myRect;
- CGrafPtr mySavedPort;
- GDHandle mySavedDevice;
-
- myAppData = (ApplicationDataHdl)NewHandleClear(sizeof(ApplicationDataRecord));
- if (myAppData != NULL) {
-
- // get the current drawing environment
- GetGWorld(&mySavedPort, &mySavedDevice);
-
- // lock the application data handle
- HLock((Handle)myAppData);
-
- // initialize the data fields to reasonable values
- (**myAppData).fWindow = (**theWindowObject).fWindow;
-
- // get the size of the destination window
- if ((**theWindowObject).fMovie != NULL) {
- GetMovieBox((**theWindowObject).fMovie, &myRect);
- }
-
- // create an offscreen GWorld that is the size of the window area
- // (this GWorld is our draw context buffer)
- myErr = NewGWorld(&(**myAppData).fGWorld, 32, &myRect, NULL, NULL, 0L);
- if (myErr != noErr)
- return(NULL);
-
- // erase the draw context buffer to our masking color
- SetGWorld((**myAppData).fGWorld, NULL);
- RGBBackColor(&kClearColor);
- EraseRect(&myRect);
-
- // restore the original drawing environment
- SetGWorld(mySavedPort, mySavedDevice);
-
- // create a new view attached to the offscreen GWorld
- (**myAppData).fView = VR3DObjects_CreateView((**myAppData).fGWorld);
-
- // create the model (the default model is a box)
- (**myAppData).fModel = VR3DObjects_CreateModel(kQ3GeometryTypeBox);
- (**myAppData).fObjectIndex = iBox;
-
- // set the drawing styles
- (**myAppData).fInterpolation = Q3InterpolationStyle_New(kQ3InterpolationStyleVertex);
- (**myAppData).fBackFacing = Q3BackfacingStyle_New(kQ3BackfacingStyleBoth);
- (**myAppData).fFillStyle = Q3FillStyle_New(kQ3FillStyleFilled);
-
- // set the rotation matrix to the identity matrix
- Q3Matrix4x4_SetIdentity(&(**myAppData).fRotation);
-
- // initialize other fields of application data structure
- (**myAppData).fGroupScale = 1.0; // set the group scale and center
- (**myAppData).fGroupCenter = myOrigin;
- (**myAppData).fTexture = NULL; // set the texture to NULL
- (**myAppData).fTextureIsMovie = false; // set the texture-is-movie flag to OFF
- (**myAppData).fObjectIsAnimated = false; // set the object animation flag to OFF
- (**myAppData).fCameraChanged = true; // set the camera-changed flag to ON
- (**myAppData).fMustRender = true; // set the render flag to ON
- (**myAppData).fQTMovieHasSound = false; // set the sound track flag to OFF
- (**myAppData).fQD3DFOVIsVert = true; // set the FOV vertical orientation flag to ON
-
- // unlock the handle
- HUnlock((Handle)myAppData);
- }
-
- return(myAppData);
- }
-
-
- //////////
- //
- // VR3DObjects_CreateModel
- // Return a display group object containing the QD3D object(s) in our model.
- //
- //////////
-
- TQ3GroupObject VR3DObjects_CreateModel (TQ3ObjectType theObjectType)
- {
- TQ3GroupObject myGroup = NULL;
- TQ3GeometryObject myObject;
- TQ3ShaderObject myIlluminationShader;
- TQ3ColorRGB myColor;
-
- // create a new display group
- myGroup = Q3DisplayGroup_New();
- if (myGroup != NULL ) {
-
- // create an illumination shader and add it to our display group
- myIlluminationShader = Q3PhongIllumination_New();
- Q3Group_AddObject(myGroup, myIlluminationShader);
-
- // set the color of the 3D object
- Q3ColorRGB_Set(&myColor, 1.0, 1.0, 1.0);
-
- // create the specified type of 3D object
- switch (theObjectType) {
- case kQ3GeometryTypeBox: { // create a box
- TQ3BoxData myBoxData;
-
- myBoxData.boxAttributeSet = Q3AttributeSet_New();
- Q3AttributeSet_Add(myBoxData.boxAttributeSet, kQ3AttributeTypeDiffuseColor, &myColor);
- myBoxData.faceAttributeSet = NULL;
- Q3Point3D_Set(&myBoxData.origin, -0.5, -0.5, -0.5);
- Q3Vector3D_Set(&myBoxData.orientation, 0, 1, 0);
- Q3Vector3D_Set(&myBoxData.majorAxis, 0, 0, 1);
- Q3Vector3D_Set(&myBoxData.minorAxis, 1, 0, 0);
- myObject = Q3Box_New(&myBoxData);
- break;
- }
-
- case kQ3GeometryTypeEllipsoid: { // create an ellipsoid
- TQ3EllipsoidData myEllipsoidData;
-
- myEllipsoidData.ellipsoidAttributeSet = Q3AttributeSet_New();
- Q3AttributeSet_Add(myEllipsoidData.ellipsoidAttributeSet, kQ3AttributeTypeDiffuseColor, &myColor);
- myEllipsoidData.interiorAttributeSet = NULL;
- myEllipsoidData.caps = NULL;
- Q3Point3D_Set(&myEllipsoidData.origin, 0.0, 0.0, 0.0);
- Q3Vector3D_Set(&myEllipsoidData.orientation, 0, 1, 0);
- Q3Vector3D_Set(&myEllipsoidData.majorRadius, 0, 0, 1);
- Q3Vector3D_Set(&myEllipsoidData.minorRadius, 1, 0, 0);
- myObject = Q3Ellipsoid_New(&myEllipsoidData);
-
- // set a finer subdivision style
- VR3DObjects_SetSubdivisionStyle(myGroup, 20);
- break;
- }
-
- case kQ3GeometryTypeCylinder: { // create a cylinder
- TQ3CylinderData myCylinderData;
-
- myCylinderData.cylinderAttributeSet = Q3AttributeSet_New();
- Q3AttributeSet_Add(myCylinderData.cylinderAttributeSet, kQ3AttributeTypeDiffuseColor, &myColor);
- myCylinderData.interiorAttributeSet = NULL;
- myCylinderData.topAttributeSet = NULL;
- myCylinderData.faceAttributeSet = NULL;
- myCylinderData.bottomAttributeSet = NULL;
- myCylinderData.caps = kQ3EndCapMaskTop | kQ3EndCapMaskBottom;
- Q3Point3D_Set(&myCylinderData.origin, 0.0, -0.5, 0.0);
- Q3Vector3D_Set(&myCylinderData.orientation, 0, 1, 0);
- Q3Vector3D_Set(&myCylinderData.majorRadius, 0, 0, 0.5);
- Q3Vector3D_Set(&myCylinderData.minorRadius, 0.5, 0, 0);
- myObject = Q3Cylinder_New(&myCylinderData);
-
- // set a finer subdivision style
- VR3DObjects_SetSubdivisionStyle(myGroup, 20);
- break;
- }
-
- case kQ3GeometryTypeCone: { // create a cone
- TQ3ConeData myConeData;
-
- myConeData.coneAttributeSet = Q3AttributeSet_New();
- Q3AttributeSet_Add(myConeData.coneAttributeSet, kQ3AttributeTypeDiffuseColor, &myColor);
- myConeData.interiorAttributeSet = NULL;
- myConeData.faceAttributeSet = NULL;
- myConeData.bottomAttributeSet = NULL;
- myConeData.caps = kQ3EndCapMaskBottom;
- Q3Point3D_Set(&myConeData.origin, 0.0, -0.5, 0.0);
- Q3Vector3D_Set(&myConeData.orientation, 0, 1, 0);
- Q3Vector3D_Set(&myConeData.majorRadius, 0, 0, 0.5);
- Q3Vector3D_Set(&myConeData.minorRadius, 0.5, 0, 0);
- myObject = Q3Cone_New(&myConeData);
- break;
- }
-
- case kQ3GeometryTypeTorus: { // create a torus
- TQ3TorusData myTorusData;
-
- myTorusData.torusAttributeSet = Q3AttributeSet_New();
- Q3AttributeSet_Add(myTorusData.torusAttributeSet, kQ3AttributeTypeDiffuseColor, &myColor);
- myTorusData.interiorAttributeSet = NULL;
- myTorusData.caps = NULL;
- myTorusData.ratio = 1.0;
- Q3Point3D_Set(&myTorusData.origin, 0.0, 0.0, 0.0);
- Q3Vector3D_Set(&myTorusData.orientation, 0, 0.3, 0);
- Q3Vector3D_Set(&myTorusData.majorRadius, 0, 0, 0.5);
- Q3Vector3D_Set(&myTorusData.minorRadius, 0.5, 0, 0);
- myObject = Q3Torus_New(&myTorusData);
-
- // set a finer subdivision style
- VR3DObjects_SetSubdivisionStyle(myGroup, 20);
- break;
- }
-
- case kQ3GeometryTypePolyhedron: { // create a polyhedron
- TQ3PolyhedronData myPolyData;
- static TQ3Vertex3D myVertices[4] = {
- { {-1.0, -1.0, 0.0}, NULL},
- { {+1.0, -1.0, 0.0}, NULL},
- { {+1.0, +1.0, 0.0}, NULL},
- { {-1.0, +1.0, 0.0}, NULL}
- };
-
- static TQ3Param2D myUVParams[4] = {
- {0.0, 0.0},
- {1.0, 0.0},
- {1.0, 1.0},
- {0.0, 1.0}
- };
-
- TQ3PolyhedronTriangleData myTriangles[2] = {
- { { 0, 1, 3 }, kQ3PolyhedronEdge01 | kQ3PolyhedronEdge20, NULL },
- { { 1, 2, 3 }, kQ3PolyhedronEdge01 | kQ3PolyhedronEdge12, NULL }
- };
-
- short myIndex;
-
- // set up vertices, edges, and triangular faces
- myPolyData.numVertices = 4;
- myPolyData.vertices = myVertices;
- myPolyData.numEdges = 0;
- myPolyData.edges = NULL;
- myPolyData.numTriangles = 2;
- myPolyData.triangles = myTriangles;
-
- // add uv parameterization to the polyhedron
- for (myIndex = 0; myIndex < myPolyData.numVertices; myIndex++) {
- myVertices[myIndex].attributeSet = Q3AttributeSet_New();
- Q3AttributeSet_Add(myVertices[myIndex].attributeSet, kQ3AttributeTypeSurfaceUV, &myUVParams[myIndex]);
- }
-
- myPolyData.polyhedronAttributeSet = Q3AttributeSet_New();
- Q3AttributeSet_Add(myPolyData.polyhedronAttributeSet, kQ3AttributeTypeDiffuseColor, &myColor);
-
- myObject = Q3Polyhedron_New(&myPolyData);
- break;
- }
-
- default:
- break;
- }
-
- // add the object to the group
- Q3Group_AddObject(myGroup, myObject);
- }
-
- // dispose of the objects we created here
- // (we can do this, because they've been added to the group)
- if (myIlluminationShader)
- Q3Object_Dispose(myIlluminationShader);
-
- if (myObject)
- Q3Object_Dispose(myObject);
-
- return(myGroup);
- }
-
-
- //////////
- //
- // VR3DObjects_CreateView
- // Return a view object for the QD3D objects in our model.
- //
- //////////
-
- TQ3ViewObject VR3DObjects_CreateView (GWorldPtr theGWorld)
- {
- TQ3Status myStatus;
- TQ3ViewObject myView;
- TQ3DrawContextObject myDrawContext;
- TQ3RendererObject myRenderer;
- TQ3CameraObject myCamera;
- TQ3GroupObject myLights;
-
- // create a new view object
- myView = Q3View_New();
- if (myView == NULL)
- goto bail;
-
- // create and set draw context
- myDrawContext = VR3DObjects_CreateDrawContext(theGWorld);
- if (myDrawContext == NULL)
- goto bail;
-
- myStatus = Q3View_SetDrawContext(myView, myDrawContext);
- if (myStatus == kQ3Failure)
- goto bail;
-
- Q3Object_Dispose(myDrawContext);
-
- // create and set renderer
- myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeInteractive);
- if (myRenderer == NULL)
- goto bail;
-
- myStatus = Q3View_SetRenderer(myView, myRenderer);
- if (myStatus == kQ3Failure)
- goto bail;
-
- Q3Object_Dispose(myRenderer);
-
- // create and set camera
- myCamera = VR3DObjects_CreateCamera(theGWorld);
- if (myCamera == NULL)
- goto bail;
-
- myStatus = Q3View_SetCamera(myView, myCamera);
- if (myStatus == kQ3Failure)
- goto bail;
-
- Q3Object_Dispose(myCamera) ;
-
- // create and set lights
- myLights = VR3DObjects_CreateLights();
- if (myLights == NULL)
- goto bail;
-
- myStatus = Q3View_SetLightGroup(myView, myLights);
- if (myStatus == kQ3Failure)
- goto bail;
-
- Q3Object_Dispose(myLights);
-
- return(myView);
-
- bail:
- // if any of the above creations failed, don't return a view
- return(NULL);
- }
-
-
- //////////
- //
- // VR3DObjects_CreateLights
- // Return a light group object for the QD3D objects in our model.
- // For displaying embedded movies, we just need the ambient light.
- //
- //////////
-
- TQ3GroupObject VR3DObjects_CreateLights (void)
- {
- TQ3GroupPosition myGroupPosition;
- TQ3GroupObject myLightList;
- TQ3LightData myLightData;
- TQ3PointLightData myPointLightData;
- TQ3DirectionalLightData myDirectionalLightData;
- TQ3LightObject myAmbientLight, myPointLight, myFillLight;
- TQ3Point3D myPointLocation = {-10.0, 0.0, 10.0};
- TQ3Vector3D myFillDirection = {10.0, 0.0, 10.0};
- TQ3ColorRGB myWhiteLight = {1.0, 1.0, 1.0};
-
- // set up light data for ambient light
- myLightData.isOn = kQ3True;
- myLightData.color = myWhiteLight;
-
- // create the ambient light
- myLightData.brightness = 1.0;
- myAmbientLight = Q3AmbientLight_New(&myLightData);
- if (myAmbientLight == NULL)
- goto bail;
-
- // create a point light
- myLightData.brightness = 1.0;
- myPointLightData.lightData = myLightData;
- myPointLightData.castsShadows = kQ3False;
- myPointLightData.attenuation = kQ3AttenuationTypeNone;
- myPointLightData.location = myPointLocation;
- myPointLight = Q3PointLight_New(&myPointLightData);
- if (myPointLight == NULL)
- goto bail;
-
- // create a directional light for fill
- myLightData.brightness = 0.2;
- myDirectionalLightData.lightData = myLightData;
- myDirectionalLightData.castsShadows = kQ3False;
- myDirectionalLightData.direction = myFillDirection;
- myFillLight = Q3DirectionalLight_New(&myDirectionalLightData);
- if (myFillLight == NULL)
- goto bail;
-
- // create a light group and add each of the lights to the group
- myLightList = Q3LightGroup_New();
- if (myLightList == NULL)
- goto bail;
- myGroupPosition = Q3Group_AddObject(myLightList, myAmbientLight);
- if (myGroupPosition == 0)
- goto bail;
- //myGroupPosition = Q3Group_AddObject(myLightList, myPointLight);
- //if (myGroupPosition == 0)
- // goto bail;
- //myGroupPosition = Q3Group_AddObject(myLightList, myFillLight);
- //if (myGroupPosition == 0)
- // goto bail;
-
- Q3Object_Dispose(myAmbientLight);
- Q3Object_Dispose(myPointLight);
- Q3Object_Dispose(myFillLight);
-
- return(myLightList);
-
- bail:
- // if any of the above creations failed, don't return a light group
- return(NULL);
- }
-
-
- //////////
- //
- // VR3DObjects_CreateDrawContext
- // Return a draw context object for the QD3D objects in our model.
- //
- //////////
-
- TQ3DrawContextObject VR3DObjects_CreateDrawContext (GWorldPtr theGWorld)
- {
- TQ3DrawContextObject myDrawContext;
- TQ3PixmapDrawContextData myPixMapDrawContextData;
- TQ3DrawContextData myDrawContextData;
- PixMapHandle myPixMap;
- Rect myRect;
- TQ3ColorARGB myClearColor = {1.0, 0.0, 0.0, 0.0};
- float myFactor = 0xffff;
-
- // set the background color;
- // note that RGBColor is defined in the range 0-65535,
- // while TQ3ColorARGB is defined in the range 0.0-1.0; hence the division....
- myClearColor.a = 0.0;
- myClearColor.r = kClearColor.red / myFactor;
- myClearColor.g = kClearColor.green / myFactor;
- myClearColor.b = kClearColor.blue / myFactor;
-
- // fill in draw context data
- myDrawContextData.clearImageMethod = kQ3ClearMethodWithColor;
- myDrawContextData.clearImageColor = myClearColor;
- myDrawContextData.paneState = kQ3False;
- myDrawContextData.maskState = kQ3False;
- myDrawContextData.doubleBufferState = kQ3False;
-
- myPixMapDrawContextData.drawContextData = myDrawContextData;
-
- myPixMap = GetGWorldPixMap(theGWorld);
- LockPixels(myPixMap);
-
- myRect = theGWorld->portRect;
-
- myPixMapDrawContextData.pixmap.width = myRect.right - myRect.left;
- myPixMapDrawContextData.pixmap.height = myRect.bottom - myRect.top;
-
- myPixMapDrawContextData.pixmap.rowBytes = (**myPixMap).rowBytes & 0x7FFF;
- myPixMapDrawContextData.pixmap.pixelType = kQ3PixelTypeRGB32;
- myPixMapDrawContextData.pixmap.pixelSize = 32;
-
- myPixMapDrawContextData.pixmap.bitOrder = kQ3EndianBig;
- myPixMapDrawContextData.pixmap.byteOrder = kQ3EndianBig;
-
- myPixMapDrawContextData.pixmap.image = GetPixBaseAddr(myPixMap);
-
- // create draw context and return it
- myDrawContext = Q3PixmapDrawContext_New(&myPixMapDrawContextData);
-
- return(myDrawContext);
- }
-
-
- //////////
- //
- // VR3DObjects_CreateCamera
- // Return a camera object for the QD3D objects in our model.
- // Note that some of the initial values are wrong and will soon be reset (in InitApplicationWindowObject).
- //
- //////////
-
- TQ3CameraObject VR3DObjects_CreateCamera (CGrafPtr thePort)
- {
- TQ3CameraObject myCamera;
- TQ3ViewAngleAspectCameraData myCameraData;
-
- TQ3Point3D myFrom = {0.0, 0.0, 0.0};
- TQ3Point3D myTo = {0.0, 0.0, -6.0}; // we're looking down negative z axis
- TQ3Vector3D myUp = {0.0, 1.0, 0.0};
-
- float myFOV = 1.00; // initial FOV really depends on QTVR instance, so we reset this in InitApplicationWindowObject
- float myHither = 0.001;
- float myYon = 100.0;
-
- myCameraData.cameraData.placement.cameraLocation = myFrom;
- myCameraData.cameraData.placement.pointOfInterest = myTo;
- myCameraData.cameraData.placement.upVector = myUp;
-
- myCameraData.cameraData.range.hither = myHither;
- myCameraData.cameraData.range.yon = myYon;
-
- // the default camera view port
- myCameraData.cameraData.viewPort.origin.x = -1.0;
- myCameraData.cameraData.viewPort.origin.y = 1.0;
- myCameraData.cameraData.viewPort.width = 2.0;
- myCameraData.cameraData.viewPort.height = 2.0;
-
- // some default FOV and aspect ratio values
- myCameraData.fov = myFOV;
- myCameraData.aspectRatioXToY =
- (float) (thePort->portRect.right - thePort->portRect.left) /
- (float) (thePort->portRect.bottom - thePort->portRect.top);
-
- myCamera = Q3ViewAngleAspectCamera_New(&myCameraData);
-
- return(myCamera);
- }
-
-
- //////////
- //
- // VR3DObjects_SetSubdivisionStyle
- // Create a subdivision style and add it to the specified group.
- //
- //////////
-
- void VR3DObjects_SetSubdivisionStyle (TQ3GroupObject theGroup, short theNumDivisions)
- {
- TQ3SubdivisionStyleData myStyleData;
- TQ3StyleObject myStyleObject;
-
- // set a subdivision style
- myStyleData.method = kQ3SubdivisionMethodConstant;
- myStyleData.c1 = theNumDivisions;
- myStyleData.c2 = theNumDivisions;
- myStyleObject = Q3SubdivisionStyle_New(&myStyleData);
- Q3Group_AddObject(theGroup, myStyleObject);
- Q3Object_Dispose(myStyleObject);
- }
-
-
- //////////
- //
- // VR3DObjects_AnimateModel
- // Animate the QuickDraw 3D model.
- //
- //////////
-
- void VR3DObjects_AnimateModel (WindowObject theWindowObject)
- {
- TQ3Matrix4x4 myMatrix;
- ApplicationDataHdl myAppData;
- TQ3Vector3D myVector;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- return;
-
- // rotate the object around the global z and local y axes
- Q3Matrix4x4_SetRotate_Z(&myMatrix, -kAnimateRadians);
- Q3Matrix4x4_Multiply(&(**myAppData).fRotation, &myMatrix, &(**myAppData).fRotation);
-
- Q3Vector3D_Set(&myVector, 0.0, 1.0, 0.0);
- Q3Matrix4x4_SetRotateAboutAxis(&myMatrix, &(**myAppData).fGroupCenter, &myVector, kAnimateRadians);
- Q3Matrix4x4_Multiply(&(**myAppData).fRotation, &myMatrix, &(**myAppData).fRotation);
- }
-
-
- //////////
- //
- // VR3DObjects_DrawModel
- // Draw the QuickDraw 3D model into the (offscreen GWorld) pixmap draw context.
- // This routine is called only in the prescreen buffer imaging complete procedure.
- //
- //////////
-
- TQ3Status VR3DObjects_DrawModel (WindowObject theWindowObject)
- {
- TQ3Status myStatus = kQ3Failure;
- ApplicationDataHdl myAppData;
- TQ3ViewObject myView;
- TQ3Vector3D myTranslate;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- return(myStatus);
-
- HLock((Handle) myAppData);
-
- myTranslate = *(TQ3Vector3D *) &(*myAppData)->fGroupCenter;
-
- myView = (**myAppData).fView;
-
- // our rendering loop
- myStatus = Q3View_StartRendering(myView);
- if (myStatus != kQ3Failure)
- do {
- Q3Style_Submit((**myAppData).fInterpolation, myView);
- Q3Style_Submit((**myAppData).fBackFacing, myView);
- Q3Style_Submit((**myAppData).fFillStyle, myView);
-
- Q3MatrixTransform_Submit(&(**myAppData).fRotation, myView);
-
- Q3TranslateTransform_Submit(&myTranslate, myView);
- Q3DisplayGroup_Submit((**myAppData).fModel, myView);
-
- } while (Q3View_EndRendering(myView) == kQ3ViewStatusRetraverse);
-
- HUnlock((Handle) myAppData);
-
- return(myStatus);
- }
-
-
- //////////
- //
- // VR3DObjects_GetModelFromFile
- // Open a model contained in a 3DMF file.
- //
- //////////
-
- void VR3DObjects_GetModelFromFile (void)
- {
- ApplicationDataHdl myAppData;
- TQ3ViewObject myView;
- OSErr myErr = noErr;
- SFTypeList myTypeList = {'3DMF'};
- StandardFileReply myReply;
- short myRefNum;
- QTVRInstance myInstance;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromFrontWindow();
- if (myAppData == NULL)
- return;
-
- myView = (**myAppData).fView;
-
- StandardGetFilePreview(0L, 1, myTypeList, &myReply);
- if (myReply.sfGood) {
-
- // this might take a while, so display the watch cursor
- SetCursor(*GetCursor(watchCursor));
-
- myErr = FSpOpenDF(&myReply.sfFile, fsRdPerm, &myRefNum);
- if (myErr == noErr) {
-
- TQ3StorageObject myStorage;
- TQ3FileObject myFile;
- TQ3Status myStatus;
- TQ3Object myModel;
- TQ3Object myObject = NULL;
- TQ3Boolean isEOF;
- TQ3GroupObject myLightGroup = NULL;
-
- // create storage and file objects
- myStorage = Q3MacintoshStorage_New(myRefNum);
- if (myStorage == NULL)
- return;
- myFile = Q3File_New();
- if (myFile == NULL)
- return;
-
- // associate the storage with the file
- Q3File_SetStorage(myFile, myStorage);
- Q3Object_Dispose(myStorage);
-
- // read the drawable objects from the file object into a new group
- myModel = Q3DisplayGroup_New();
- if (myModel != NULL) {
- myStatus = Q3File_OpenRead(myFile, NULL);
- if (myStatus == kQ3Success) {
-
- do {
- myObject = Q3File_ReadObject(myFile);
-
- // if object read is not NULL then process object
- if (myObject != NULL) {
- if (Q3Object_IsDrawable(myObject))
- Q3Group_AddObject(myModel, myObject);
-
- //if (Q3Object_IsType(myObject, kQ3SharedTypeViewHints))
- // if (myView)
- // Q3ViewHints_GetLightGroup((TQ3ViewHintsObject)myObject, &myLightGroup);
-
- Q3Object_Dispose(myObject);
- }
-
- isEOF = Q3File_IsEndOfFile(myFile);
- } while (isEOF == kQ3False);
-
- if (myLightGroup) {
- Q3View_SetLightGroup(myView, myLightGroup);
- Q3Object_Dispose(myLightGroup);
- }
- else {
- myLightGroup = VR3DObjects_CreateLights();
- Q3View_SetLightGroup(myView, myLightGroup);
- Q3Object_Dispose(myLightGroup);
- }
- }
-
- // install new model in application data structure
- (**myAppData).fModel = myModel;
-
- // reset the rotation matrix to the identity matrix
- Q3Matrix4x4_SetIdentity(&(**myAppData).fRotation);
-
- // reset other model parameters
- Q3Point3D_Set(&(**myAppData).fGroupCenter, 0.0, 0.0, 0.0);
- (**myAppData).fGroupScale = 1.0;
- (**myAppData).fTexture = NULL;
- (**myAppData).fTextureIsMovie = false;
- (**myAppData).fObjectIndex = i3DMFFile; // not a predefined object
- }
-
- // close the file object
- Q3File_Close(myFile);
-
- // close the file, since we've got the data we need
- FSClose(myRefNum);
-
- // redraw the screen (to display new model)
- (**myAppData).fMustRender = true;
- myInstance = GetQTVRInstanceFromFrontWindow();
- QTVRUpdate(myInstance, kQTVRCurrentMode);
- }
- } else {
- // if the user didn't select a file, we force a box
- (**myAppData).fModel = VR3DObjects_CreateModel(kQ3GeometryTypeBox);
- }
-
- // restore original cursor
- SetCursor(&qd.arrow);
- }
-
-
- //////////
- //
- // VR3DObjects_InstallPrescreenRoutine
- // Install a prescreen buffer imaging complete procedure
- // to copy the rendered 3D image into the prescreen buffer (whence QTVR puts it on the screen).
- //
- //////////
-
- void VR3DObjects_InstallPrescreenRoutine (QTVRInstance theInstance, WindowObject theWindowObject)
- {
- ImagingCompleteUPP myImagingProc;
-
- myImagingProc = NewImagingCompleteProc(VR3DObjects_PrescreenRoutine);
- QTVRSetPrescreenImagingCompleteProc(theInstance, myImagingProc, (SInt32)theWindowObject, 0);
-
- // we want our prescreen imaging procedure to be called *every* time a QTVR image is drawn,
- // so we must turn off direct screen drawing for all drawing modes (both motion and static)
- QTVRSetImagingProperty(theInstance, kQTVRAllModes, kQTVRImagingDirectDraw, 0);
- }
-
-
- ///////////
- //
- // VR3DObjects_InstallInterceptRoutine
- // Install a QTVR intercept procedure to signal that the camera needs to be updated.
- //
- //////////
-
- void VR3DObjects_InstallInterceptRoutine (QTVRInstance theInstance, WindowObject theWindowObject)
- {
- QTVRInterceptUPP myInterceptProc;
-
- myInterceptProc = NewQTVRInterceptProc(VR3DObjects_InterceptRoutine);
-
- // we'll just use the same intercept proc for each intercepted procedure
- QTVRInstallInterceptProc(theInstance, kQTVRSetPanAngleSelector, myInterceptProc, (SInt32)theWindowObject, 0);
- QTVRInstallInterceptProc(theInstance, kQTVRSetTiltAngleSelector, myInterceptProc, (SInt32)theWindowObject, 0);
- QTVRInstallInterceptProc(theInstance, kQTVRSetFieldOfViewSelector, myInterceptProc, (SInt32)theWindowObject, 0);
- }
-
-
- ///////////
- //
- // VR3DObjects_PrescreenRoutine
- // Draw the rendered 3D scene into the current graphics world.
- //
- //////////
-
- pascal OSErr VR3DObjects_PrescreenRoutine (QTVRInstance theInstance, WindowObject theWindowObject)
- {
- #pragma unused(theInstance)
-
- ApplicationDataHdl myAppData;
- CGrafPtr myGWorld;
- GDHandle myGDevice;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- return(paramErr);
-
- HLock((Handle)myAppData);
-
- // if there is an active movie texture, advance the movie to the next frame
- if ((**myAppData).fTexture) {
- if ((**myAppData).fTextureIsMovie)
- VR3DTexture_NextFrame((**myAppData).fTexture);
- (**myAppData).fMustRender = true;
- }
-
- // if animation is active, animate the model
- if ((**myAppData).fObjectIsAnimated) {
- VR3DObjects_AnimateModel(theWindowObject);
- (**myAppData).fMustRender = true;
- }
-
- // if the camera needs to be updated, do so
- if ((**myAppData).fCameraChanged) {
- VR3DObjects_SetCamera(theWindowObject);
- (**myAppData).fMustRender = true;
- }
-
- // if a new image needs to be rendered, do so and clear the render flag
- if ((**myAppData).fMustRender) {
- VR3DObjects_DrawModel(theWindowObject);
- (**myAppData).fMustRender = false;
- }
-
- // on entry, the current graphics world is set to the prescreen buffer
- GetGWorld(&myGWorld, &myGDevice);
-
- OpColor(&kClearColor);
- RGBBackColor(&kClearColor);
-
- // copy the rendered image to the prescreen buffer
- CopyBits((BitMapPtr) &(**myAppData).fGWorld->portPixMap,
- (BitMapPtr)&(**(myGWorld->portPixMap)).baseAddr,
- &(**myAppData).fGWorld->portRect,
- &(**(myGWorld->portPixMap)).bounds,
- srcCopy | transparent,
- 0L);
-
- HUnlock((Handle)myAppData);
-
- return(noErr);
- }
-
-
- //////////
- //
- // VR3DObjects_InterceptRoutine
- // Signal that the camera needs to be updated.
- // (We could easily do this elsewhere, but this works for now....)
- //
- //////////
-
- pascal void VR3DObjects_InterceptRoutine (QTVRInstance theInstance, QTVRInterceptPtr theMsg, WindowObject theWindowObject, Boolean *cancel)
- {
- #pragma unused(theInstance)
-
- Boolean myCancelInterceptedProc = false; // true == do NOT call thru; false == call thru
- ApplicationDataHdl myAppData;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- return;
-
- switch (theMsg->selector) {
-
- case kQTVRSetPanAngleSelector:
- case kQTVRSetTiltAngleSelector:
- case kQTVRSetFieldOfViewSelector:
- (**myAppData).fCameraChanged = true;
- break;
- default:
- break;
- }
-
- *cancel = myCancelInterceptedProc;
- }
-
-
- //////////
- //
- // VR3DObjects_SetCamera
- // Set the point-of-interest and FOV of the 3D camera associated with the specified window object.
- //
- //////////
-
- void VR3DObjects_SetCamera (WindowObject theWindowObject)
- {
- ApplicationDataHdl myAppData;
- TQ3ViewObject myView;
- TQ3CameraObject myCamera;
- TQ3CameraPlacement myCameraPos;
- QTVRInstance myInstance;
-
- // get the QTVR instance associated with the specified window
- if (theWindowObject == NULL)
- return;
-
- myInstance = (**theWindowObject).fInstance;
- if (myInstance == NULL)
- return;
-
- // get the view object associated with the specified window
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- return;
- myView = (**myAppData).fView;
-
- // get the camera
- Q3View_GetCamera(myView, &myCamera);
- if (myCamera != NULL) {
- float myFOV, myPan, myTilt;
- TQ3Point3D myPoint;
-
- // set the camera's field of view
- myFOV = QTVRGetFieldOfView(myInstance);
- if ((**myAppData).fQD3DFOVIsVert) {
- Q3ViewAngleAspectCamera_SetFOV(myCamera, myFOV);
- } else {
- float myRatio;
-
- Q3ViewAngleAspectCamera_GetAspectRatio(myCamera, &myRatio);
- Q3ViewAngleAspectCamera_SetFOV(myCamera, myFOV * myRatio);
- }
-
- // set the camera's point of interest, based on current pan and tilt angles
- myPan = QTVRGetPanAngle(myInstance);
- myTilt = QTVRGetTiltAngle(myInstance);
-
- myPoint.x = -sin(myPan) * cos(myTilt) * k3DObjectDistance;
- myPoint.y = sin(myTilt) * k3DObjectDistance;
- myPoint.z = -cos(myPan) * cos(myTilt) * k3DObjectDistance;
-
- Q3Camera_GetPlacement(myCamera, &myCameraPos);
- myCameraPos.pointOfInterest = myPoint;
-
- // update the QD3D camera
- Q3Camera_SetPlacement(myCamera, &myCameraPos);
- Q3View_SetCamera(myView, myCamera);
- Q3Object_Dispose(myCamera);
- }
- }
-
-
- //////////
- //
- // VR3DObjects_SetCameraAspectRatio
- // Adjust the aspect ratio of the QuickDraw 3D camera based on current window shape.
- //
- //////////
-
- void VR3DObjects_SetCameraAspectRatio (WindowObject theWindowObject)
- {
- ApplicationDataHdl myAppData;
- TQ3ViewObject myView;
- TQ3CameraObject myCamera;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- return;
-
- // get the window's view and camera objects
- myView = (**myAppData).fView;
- Q3View_GetCamera(myView, &myCamera);
-
- // adjust the aspect ratio of the camera
- if (myCamera != NULL) {
- Rect myRect;
- float myRatio;
-
- // get the size of the specified window
- if ((**theWindowObject).fMovie != NULL)
- GetMovieBox((**theWindowObject).fMovie, &myRect);
-
- // calculate the aspect ratio of the movie rectangle
- myRatio = (float)(myRect.right - myRect.left) / (float)(myRect.bottom - myRect.top);
-
- // determine whether QD3D FOV is horizontal or vertical
- (**myAppData).fQD3DFOVIsVert = (myRatio >= 1.0);
-
- // adjust camera's aspect ratio
- Q3ViewAngleAspectCamera_SetAspectRatio(myCamera, myRatio);
- Q3Object_Dispose(myCamera);
- }
- }
-
-
- //////////
- //
- // VR3DObjects_UpdateDrawContext
- // Delete current draw context and create a new one based on current window size.
- //
- //////////
-
- void VR3DObjects_UpdateDrawContext (WindowObject theWindowObject)
- {
- ApplicationDataHdl myAppData;
- TQ3ViewObject myView;
- TQ3DrawContextObject myDrawContext;
- CGrafPtr mySavedPort;
- GDHandle mySavedDevice;
- Rect myRect;
- OSErr myErr;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- return;
-
- // lock the application data handle
- HLock((Handle)myAppData);
-
- // get the window's view and draw context objects
- myView = (**myAppData).fView;
- Q3View_GetDrawContext(myView, &myDrawContext);
-
- // get the size of the specified window
- if ((**theWindowObject).fMovie != NULL)
- GetMovieBox((**theWindowObject).fMovie, &myRect);
-
- // get the current drawing environment
- GetGWorld(&mySavedPort, &mySavedDevice);
-
- // dispose of the current draw context GWorld
- DisposeGWorld((**myAppData).fGWorld);
-
- // create a new offscreen GWorld that is the size of the window area
- myErr = NewGWorld(&(**myAppData).fGWorld, 32, &myRect, NULL, NULL, 0L);
- if (myErr != noErr)
- return;
-
- // erase the draw context buffer to our masking color
- SetGWorld((**myAppData).fGWorld, NULL);
- RGBBackColor(&kClearColor);
- EraseRect(&myRect);
-
- // restore the original drawing environment
- SetGWorld(mySavedPort, mySavedDevice);
-
- if (myDrawContext != NULL) {
- // get rid of existing draw context
- Q3Object_Dispose(myDrawContext);
-
- // create and set draw context
- myDrawContext = VR3DObjects_CreateDrawContext((**myAppData).fGWorld);
- Q3View_SetDrawContext(myView, myDrawContext);
- Q3Object_Dispose(myDrawContext);
- }
-
- HUnlock((Handle)myAppData);
- }
-
-
- //////////
- //
- // VR3DObjects_GetEmbeddedMovie
- // Get the QuickTime movie to be used as a texture map.
- // Returns a Boolean to indicate success (true) or failure (false).
- //
- //////////
-
- Boolean VR3DObjects_GetEmbeddedMovie (Movie *theMoviePtr)
- {
- StandardFileReply myReply;
- short myNumTypes = 1;
- SFTypeList myTypes = {'MooV', 0};
-
- // clean up any previous movie
- if (*theMoviePtr != NULL) {
- StopMovie(*theMoviePtr);
- DisposeMovie(*theMoviePtr);
- *theMoviePtr = NULL;
- }
-
- // elicit the movie file from user
- StandardGetFilePreview(NULL, myNumTypes, myTypes, &myReply);
- if (!myReply.sfGood)
- return(false);
-
- return(VR3DObjects_LoadEmbeddedMovie(&myReply.sfFile, theMoviePtr));
- }
-
-
- //////////
- //
- // VR3DObjects_LoadEmbeddedMovie
- // Load the QuickTime movie in the specified file.
- // Returns a Boolean to indicate success (true) or failure (false).
- //
- //////////
-
- Boolean VR3DObjects_LoadEmbeddedMovie (FSSpec *theMovieFile, Movie *theMoviePtr)
- {
- OSErr myErr = noErr;
- short myMovieFileRef;
- Rect myRect;
-
- // open the movie
- myErr = OpenMovieFile(theMovieFile, &myMovieFileRef, fsRdPerm);
- if (myErr != noErr)
- return(false);
-
- myErr = NewMovieFromFile(theMoviePtr, myMovieFileRef, NULL, (StringPtr)NULL, newMovieActive, NULL);
- if (myErr != noErr)
- return(false);
-
- CloseMovieFile(myMovieFileRef);
-
- SetMovieMatrix(*theMoviePtr, NULL);
-
- SetRect(&myRect, 0, 0, 128, 128);
- SetMovieBox(*theMoviePtr, &myRect);
-
- return(true);
- }
-
-
- //////////
- //
- // VR3DObjects_LoopEmbeddedMovie
- // Start the QuickTime movie playing in a loop.
- //
- //////////
-
- void VR3DObjects_LoopEmbeddedMovie (Movie theMovie, GWorldPtr theGWorld)
- {
- TimeBase myTimeBase;
-
- SetMovieGWorld(theMovie, theGWorld, nil);
-
- // draw the movie first
- MoviesTask(theMovie, 0);
- MoviesTask(theMovie, 0);
-
- // throw the movie into loop mode
- myTimeBase = GetMovieTimeBase(theMovie);
- SetTimeBaseFlags(myTimeBase, GetTimeBaseFlags(myTimeBase) | loopTimeBase);
-
- // start playing the movie
- StartMovie(theMovie);
- }
-
-
- //////////
- //
- // VR3DObjects_GetEmbeddedPicture
- // Get the picture to be used as a texture map from a PICT file.
- // (This routine is modeled on IM: Imaging With QuickDraw, pp. 7-13f.)
- //
- //////////
-
- PicHandle VR3DObjects_GetEmbeddedPicture (void)
- {
- OSErr myErr = noErr;
- SFTypeList myTypeList = {'PICT'};
- StandardFileReply myReply;
- short myNumTypes = 1;
- short myRefNum;
- long myLength;
- PicHandle myPicture = NULL;
-
- // elicit the picture file from user
- StandardGetFilePreview(NULL, myNumTypes, myTypeList, &myReply);
- if (myReply.sfGood) {
-
- // open the picture file and read in picture data
- myErr = FSpOpenDF(&myReply.sfFile, fsRdPerm, &myRefNum);
- if (myErr == noErr) {
- myErr = GetEOF(myRefNum, &myLength);
- if (myErr != noErr)
- return(myPicture);
-
- myErr = SetFPos(myRefNum, fsFromStart, kPicFileHeaderSize);
- myLength -= kPicFileHeaderSize;
- myPicture = (PicHandle)NewHandleClear(myLength);
- if ((myErr == noErr) && (myPicture != NULL)) {
- HLock((Handle)myPicture);
- myErr = FSRead(myRefNum, &myLength, (Ptr)*myPicture);
- HUnlock((Handle)myPicture);
- }
-
- // close the file, since we've got the data we need
- FSClose(myRefNum);
- }
- }
-
- return(myPicture);
- }
-
-
- //////////
- //
- // VR3DObjects_FadeObjects
- // Fade the 3D model in or out.
- //
- //////////NOT WORKING QUITE YET
-
- void VR3DObjects_FadeObjects (ApplicationDataHdl theAppData, Boolean isShow)
- {
- TQ3ViewObject myView;
- TQ3GroupObject myGroup;
- TQ3GroupPosition myPos;
- TQ3Object myLight;
- TQ3Status myStatus;
- TQ3ColorRGB myColor;
- float myIndex;
-
- if (theAppData == NULL)
- return;
-
- // get the view and the 3D model
- myView = (**theAppData).fView;
- if (myView == NULL)
- return;
-
- myStatus = Q3View_GetLightGroup(myView, &myGroup);
- if (myStatus == kQ3Success) {
- for (Q3Group_GetFirstPosition(myGroup, &myPos); myPos != NULL; Q3Group_GetNextPosition(myGroup, &myPos)) {
- myStatus = Q3Group_GetPositionObject(myGroup, myPos, &myLight);
- if (myStatus != kQ3Success)
- break;
-
- if (isShow) {
- for (myIndex = 0.0; myIndex < 1.0; myIndex += 0.1) {
- Q3ColorRGB_Set(&myColor, myIndex, 1.0, myIndex);
- Q3Light_SetColor(myLight, &myColor);
- //QTVRUpdate(myInstance, kQTVRCurrentMode);
- }
- } else {
- for (myIndex = 1.0; myIndex > 0.0; myIndex -= 0.1) {
- Q3ColorRGB_Set(&myColor, myIndex, 1.0, myIndex);
- Q3Light_SetColor(myLight, &myColor);
- //QTVRUpdate(myInstance, kQTVRCurrentMode);
- }
- }
-
- Q3Object_Dispose(myLight);
- }
- }
- }